package com.gamesite.gamesite.games.TicTacToe.pojo;

import javax.websocket.Session;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class TicTacToeGame {
    private final Long roomId;
    private final List<Long> players = new CopyOnWriteArrayList<>();
    private final Map<Long, Session> playerSessions = new ConcurrentHashMap<>();
    private final Map<Long, String> playerSymbols = new ConcurrentHashMap<>();
    private Long hostId;
    private Long currentPlayerId;
    private Long winnerId;
    private boolean gameOver;
    private String[] board = new String[9];
    private int[] winningCombo;

    public TicTacToeGame(Long roomId) {
        this.roomId = roomId;
        Arrays.fill(board, "");
    }

    public synchronized boolean addPlayer(Long userId, boolean isHost, Session session) {
        if (players.size() >= 2) return false;

        players.add(userId);
        playerSessions.put(userId, session);

        if (isHost) {
            hostId = userId;
            playerSymbols.put(userId, "X");
            currentPlayerId = userId; // 房主先手
        } else {
            playerSymbols.put(userId, "O");
        }

        return true;
    }

    public void startGame() {
        gameOver = false;
        winnerId = null;
        winningCombo = null;
        Arrays.fill(board, "");
        currentPlayerId = hostId;
    }

    public synchronized boolean makeMove(Long playerId, int index) {
        if (gameOver || !playerId.equals(currentPlayerId) || index < 0 || index >= 9 || !board[index].isEmpty()) {
            return false;
        }

        board[index] = playerSymbols.get(playerId);
        return true;
    }

    public boolean checkWinner() {
        int[][] winCombinations = {
                {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // 横排
                {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // 竖排
                {0, 4, 8}, {2, 4, 6}              // 对角线
        };

        for (int[] combo : winCombinations) {
            if (!board[combo[0]].isEmpty() &&
                    board[combo[0]].equals(board[combo[1]]) &&
                    board[combo[0]].equals(board[combo[2]])) {

                winnerId = players.get(playerSymbols.get(players.get(0)).equals(board[combo[0]]) ? 0 : 1);
                winningCombo = combo;
                gameOver = true;
                return true;
            }
        }

        return false;
    }

    public boolean isBoardFull() {
        for (String cell : board) {
            if (cell.isEmpty()) {
                return false;
            }
        }
        gameOver = true;
        return true;
    }

    public void endGame(Long winnerId) {
        this.winnerId = winnerId;
        this.gameOver = true;
    }

    public void switchTurn() {
        currentPlayerId = players.get((players.indexOf(currentPlayerId) + 1) % 2);
    }

    public void resetGame() {
        startGame();
    }

    public synchronized void removePlayer(Long userId) {
        players.remove(userId);
        playerSessions.remove(userId);
        playerSymbols.remove(userId);
    }

    public boolean isCurrentPlayer(Long userId) {
        return userId.equals(currentPlayerId);
    }

    public boolean isHost(Long userId) {
        return userId.equals(hostId);
    }

    public Map<String, Object> getGameState() {
        Map<String, Object> state = new HashMap<>();
        state.put("type", "gameState");
        state.put("roomId", roomId);
        state.put("board", board);
        state.put("currentPlayerId", currentPlayerId);
        state.put("winnerId", winnerId);
        state.put("gameOver", gameOver);
        state.put("winningCombo", winningCombo);

        List<Map<String, Object>> playersInfo = new ArrayList<>();
        for (Long playerId : players) {
            Map<String, Object> playerInfo = new HashMap<>();
            playerInfo.put("id", playerId);
            playerInfo.put("symbol", playerSymbols.get(playerId));
            playerInfo.put("isHost", playerId.equals(hostId));
            playersInfo.add(playerInfo);
        }
        state.put("players", playersInfo);

        return state;
    }

    // Getters
    public Long getRoomId() { return roomId; }
    public List<Long> getPlayers() { return players; }
    public Collection<Session> getPlayerSessions() { return playerSessions.values(); }
    public Long getCurrentPlayerId() { return currentPlayerId; }
    public Long getWinnerId() { return winnerId; }
    public boolean isGameOver() { return gameOver; }
    public String[] getBoard() { return board; }
    public int[] getWinningCombo() { return winningCombo; }
}